{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#  TensorFlow入门（一）基本用法\n",
    "<br/>refer to: http://wiki.jikexueyuan.com/project/tensorflow-zh/get_started/basic_usage.html\n",
    "<br/>@author: huangyongye\n",
    "<br/>@date: 2017-02-25\n",
    "<br/><br/>本例子主要是按照 tensorflow的中文文档来学习 tensorflow 的基本用法。按照文档说明，主要存在的一些问题：\n",
    "<br/>\n",
    "- 1.就是 Session() 和 InteractiveSession() 的用法。后者用 Tensor.eval() 和 Operation.run() 来替代了 Session.run(). 其中更多的是用 Tensor.eval()，所有的表达式都可以看作是 Tensor. \n",
    "- 2.另外，tf的表达式中所有的变量或者是常量都应该是 tf 的类型。\n",
    "- 3.只要是声明了变量，就得用 sess.run(tf.global_variables_initializer()) 或者 x.initializer.run() 方法来初始化才能用。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 例一：平面拟合\n",
    "通过本例可以看到机器学习的一个通用过程：1.准备数据  -> 2.构造模型（设置求解目标函数）  -> 3.求解模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 [[ 0.27467242  0.81889796]] [-0.13746099]\n",
      "20 [[ 0.1619305   0.39317462]] [ 0.18206716]\n",
      "40 [[ 0.11901411  0.25831661]] [ 0.2642329]\n",
      "60 [[ 0.10580806  0.21761954]] [ 0.28916073]\n",
      "80 [[ 0.10176832  0.20532639]] [ 0.29671678]\n",
      "100 [[ 0.10053726  0.20161074]] [ 0.29900584]\n",
      "120 [[ 0.100163    0.20048723]] [ 0.29969904]\n",
      "140 [[ 0.10004941  0.20014738]] [ 0.29990891]\n",
      "160 [[ 0.10001497  0.20004457]] [ 0.29997244]\n",
      "180 [[ 0.10000452  0.20001349]] [ 0.29999167]\n",
      "200 [[ 0.10000138  0.2000041 ]] [ 0.29999748]\n"
     ]
    }
   ],
   "source": [
    "import tensorflow as tf\n",
    "import numpy as np\n",
    "\n",
    "# 1.准备数据：使用 NumPy 生成假数据(phony data), 总共 100 个点.\n",
    "x_data = np.float32(np.random.rand(2, 100)) # 随机输入\n",
    "y_data = np.dot([0.100, 0.200], x_data) + 0.300\n",
    "\n",
    "# 2.构造一个线性模型\n",
    "b = tf.Variable(tf.zeros([1]))\n",
    "W = tf.Variable(tf.random_uniform([1, 2], -1.0, 1.0))\n",
    "y = tf.matmul(W, x_data) + b\n",
    "\n",
    "# 3.求解模型\n",
    "# 设置损失函数：误差的均方差\n",
    "loss = tf.reduce_mean(tf.square(y - y_data))\n",
    "# 选择梯度下降的方法\n",
    "optimizer = tf.train.GradientDescentOptimizer(0.5)\n",
    "# 迭代的目标：最小化损失函数\n",
    "train = optimizer.minimize(loss)\n",
    "\n",
    "\n",
    "############################################################\n",
    "# 以下是用 tf 来解决上面的任务\n",
    "# 1.初始化变量：tf 的必备步骤，主要声明了变量，就必须初始化才能用\n",
    "init = tf.global_variables_initializer()\n",
    "\n",
    "\n",
    "# 设置tensorflow对GPU的使用按需分配\n",
    "config  = tf.ConfigProto()\n",
    "config.gpu_options.allow_growth = True\n",
    "# 2.启动图 (graph)\n",
    "sess = tf.Session(config=config)\n",
    "sess.run(init)\n",
    "\n",
    "# 3.迭代，反复执行上面的最小化损失函数这一操作（train op）,拟合平面\n",
    "for step in xrange(0, 201):\n",
    "    sess.run(train)\n",
    "    if step % 20 == 0:\n",
    "        print step, sess.run(W), sess.run(b)\n",
    "\n",
    "# 得到最佳拟合结果 W: [[0.100  0.200]], b: [0.300]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 例二：两个数求和"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[15.0, 5.0]\n",
      "<type 'list'>\n",
      "<type 'numpy.float32'>\n"
     ]
    }
   ],
   "source": [
    "input1 = tf.constant(2.0)\n",
    "input2 = tf.constant(3.0)\n",
    "input3 = tf.constant(5.0)\n",
    "\n",
    "intermd = tf.add(input1, input2)\n",
    "mul = tf.multiply(input2, input3)\n",
    "\n",
    "with tf.Session() as sess:\n",
    "    result = sess.run([mul, intermd])  # 一次执行多个op\n",
    "    print result\n",
    "    print type(result)\n",
    "    print type(result[0])   "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 1.变量，常量\n",
    "1.1 用 tensorflow 实现计数器，主要是设计了 在循环中调用加法实现计数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n",
      "1\n",
      "2\n",
      "3\n"
     ]
    }
   ],
   "source": [
    "# 创建变量，初始化为0\n",
    "state = tf.Variable(0, name=\"counter\")\n",
    "\n",
    "# 创建一个 op , 其作用是时 state 增加 1\n",
    "one = tf.constant(1) # 直接用 1 也就行了\n",
    "new_value = tf.add(state, 1)\n",
    "update = tf.assign(state, new_value)\n",
    "\n",
    "\n",
    "# 启动图之后， 运行 update op\n",
    "with tf.Session() as sess:\n",
    "    # 创建好图之后，变量必须经过‘初始化’ \n",
    "    sess.run(tf.global_variables_initializer())\n",
    "    # 查看state的初始化值\n",
    "    print sess.run(state)\n",
    "    for _ in range(3):\n",
    "        sess.run(update)  # 这样子每一次运行state 都还是1\n",
    "        print sess.run(state)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "1.2 用 tf 来实现对一组数求和，再计算平均"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " s_sum = 0.0\n",
      "vec =  [ 1.  2.  3.  4.]\n",
      "h_sum = 1.0\n",
      "h_sum = 3.0\n",
      "h_sum = 6.0\n",
      "h_sum = 10.0\n",
      "the mean is  2.5\n"
     ]
    }
   ],
   "source": [
    "h_sum = tf.Variable(0.0, dtype=tf.float32)\n",
    "# h_vec = tf.random_normal(shape=([10]))\n",
    "h_vec = tf.constant([1.0,2.0,3.0,4.0])\n",
    "# 把 h_vec 的每个元素加到 h_sum 中，然后再除以 10 来计算平均值\n",
    "# 待添加的数\n",
    "h_add = tf.placeholder(tf.float32)\n",
    "# 添加之后的值\n",
    "h_new = tf.add(h_sum, h_add)\n",
    "# 更新 h_new 的 op\n",
    "update = tf.assign(h_sum, h_new)\n",
    "\n",
    "with tf.Session() as sess:\n",
    "    sess.run(tf.global_variables_initializer())\n",
    "    # 查看原始值\n",
    "    print 's_sum =', sess.run(h_sum)\n",
    "    print \"vec = \", sess.run(h_vec)\n",
    "    \n",
    "    # 循环添加\n",
    "    for _ in range(4):\n",
    "        sess.run(update, feed_dict={h_add: sess.run(h_vec[_])})\n",
    "        print 'h_sum =', sess.run(h_sum)\n",
    "    \n",
    "#     print 'the mean is ', sess.run(sess.run(h_sum) / 4)  # 这样写 4  是错误的， 必须转为 tf 变量或者常量\n",
    "    print 'the mean is ', sess.run(sess.run(h_sum) / tf.constant(4.0))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "init state  0.0\n",
      "1.0\n",
      "2.0\n",
      "3.0\n"
     ]
    }
   ],
   "source": [
    "import tensorflow as tf\n",
    "config = tf.ConfigProto()\n",
    "config.gpu_options.allow_growth = True\n",
    "sess = tf.Session(config=config)\n",
    "# 如果不是 assign() 重新赋值的话，每一次 sess.run()都会把 state再次初始化为 0.0\n",
    "state = tf.Variable(0.0, tf.float32)\n",
    "# 通过 assign 操作来改变state的值。\n",
    "add_op = tf.assign(state, state+1)\n",
    "\n",
    "sess.run(tf.global_variables_initializer())\n",
    "print 'init state ', sess.run(state)\n",
    "for _ in xrange(3):\n",
    "    sess.run(add_op)\n",
    "    print sess.run(state)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 在函数内部用 assign 不会改变外边的值呀"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "THE INIT W IS  [ 0.2         0.30000001  0.40000001]\n",
      "AFTER RUNNING THE FUNC  [ 0.2         0.30000001  0.40000001]\n"
     ]
    }
   ],
   "source": [
    "def chang_W(W1):\n",
    "    tf.assign(W1, [1.1, 1.2,1.3])\n",
    "    \n",
    "W = tf.get_variable('Weights', initializer=[0.2, 0.3, 0.4])\n",
    "sess.run(tf.global_variables_initializer())\n",
    "print 'THE INIT W IS ', sess.run(W)\n",
    "chang_W(W)\n",
    "print 'AFTER RUNNING THE FUNC ', sess.run(W)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#   2. InteractiveSession() 的用法\n",
    "InteractiveSession() 主要是避免 Session（会话）被一个变量持有"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3.0\n",
      "3.0\n"
     ]
    }
   ],
   "source": [
    "a = tf.constant(1.0)\n",
    "b = tf.constant(2.0)\n",
    "c = a + b\n",
    "\n",
    "# 下面的两种情况是等价的\n",
    "with tf.Session():\n",
    "    print c.eval()\n",
    "    \n",
    "sess = tf.InteractiveSession()\n",
    "print c.eval()\n",
    "sess.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.0\n",
      "3.0\n",
      "1.2\n"
     ]
    }
   ],
   "source": [
    "a = tf.constant(1.0)\n",
    "b = tf.constant(2.0)\n",
    "c = tf.Variable(3.0)\n",
    "d = a + b\n",
    "\n",
    "sess = tf.InteractiveSession()\n",
    "sess.run(tf.global_variables_initializer())\n",
    "\n",
    "###################\n",
    "# 这样写是错误的\n",
    "# print a.run()  \n",
    "# print d.run()\n",
    "\n",
    "####################\n",
    "\n",
    "# 这样才是正确的\n",
    "print a.eval()   \n",
    "print d.eval()\n",
    "\n",
    "# run() 方法主要用来\n",
    "x = tf.Variable(1.2)\n",
    "# print x.eval()  # 还没初始化，不能用\n",
    "x.initializer.run()  # x.initializer 就是一个初始化的 op， op才调用run() 方法\n",
    "print x.eval()\n",
    "\n",
    "sess.close()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 怎样使用 tf.InteractiveSession() 来完成上面 1.2 中 求和 、平均 的操作呢?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "s_sum = 0.0\n",
      "vec =  [ 1.  2.  3.  4.]\n",
      "vec =  1.0\n",
      "h_sum = 1.0\n",
      "h_sum = 3.0\n",
      "h_sum = 6.0\n",
      "h_sum = 10.0\n"
     ]
    }
   ],
   "source": [
    "h_sum = tf.Variable(0.0, dtype=tf.float32)\n",
    "# h_vec = tf.random_normal(shape=([10]))\n",
    "h_vec = tf.constant([1.0,2.0,3.0,4.0])\n",
    "# 把 h_vec 的每个元素加到 h_sum 中，然后再除以 10 来计算平均值\n",
    "# 待添加的数\n",
    "h_add = tf.placeholder(tf.float32)\n",
    "# 添加之后的值\n",
    "h_new = tf.add(h_sum, h_add)\n",
    "# 更新 h_new 的 op\n",
    "update = tf.assign(h_sum, h_new)\n",
    "\n",
    "sess = tf.InteractiveSession()\n",
    "sess.run(tf.global_variables_initializer())\n",
    "print 's_sum =', h_sum.eval()\n",
    "print \"vec = \", h_vec.eval()\n",
    "print \"vec = \", h_vec[0].eval()\n",
    "\n",
    "\n",
    "for _ in range(4):\n",
    "    update.eval(feed_dict={h_add: h_vec[_].eval()})\n",
    "    print 'h_sum =', h_sum.eval()\n",
    "sess.close()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3.使用feed来对变量赋值\n",
    "这些需要用到feed来赋值的操作可以通过tf.placeholder()说明，以创建占位符。\n",
    "<br/> 下面的例子中可以看出 session.run([output], ...) 和 session.run(output, ...) 的区别。前者输出了 output 的类型等详细信息，后者只输出简单结果。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[array([ 14.], dtype=float32)]\n"
     ]
    }
   ],
   "source": [
    "input1 = tf.placeholder(tf.float32)\n",
    "input2 = tf.placeholder(tf.float32)\n",
    "output = tf.multiply(input1, input2)\n",
    "\n",
    "with tf.Session() as sess:\n",
    "    print sess.run([output], feed_dict={input1:[7.0], input2:[2.0]})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<type 'numpy.ndarray'>\n",
      "[ 14.]\n"
     ]
    }
   ],
   "source": [
    "with tf.Session() as sess:\n",
    "    result = sess.run(output, feed_dict={input1:[7.0], input2:[2.0]})\n",
    "    print type(result)\n",
    "    print result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<type 'numpy.float32'>\n",
      "14.0\n"
     ]
    }
   ],
   "source": [
    "with tf.Session() as sess:\n",
    "    result = sess.run(output, feed_dict={input1:7.0, input2:2.0})\n",
    "    print type(result)\n",
    "    print result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[array([ 14.,   3.], dtype=float32)]\n"
     ]
    }
   ],
   "source": [
    "with tf.Session() as sess:\n",
    "    print sess.run([output], feed_dict={input1:[7.0, 3.0], input2:[2.0, 1.0]})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 14.   3.]\n"
     ]
    }
   ],
   "source": [
    "with tf.Session() as sess:\n",
    "    print sess.run(output, feed_dict={input1:[7.0, 3.0], input2:[2.0, 1.0]})"
   ]
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python [conda root]",
   "language": "python",
   "name": "conda-root-py"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
